package com.ruoyi.web.core.redpacket;

import com.ruoyi.web.core.utils.SendResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import javax.net.ssl.SSLContext;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.Iterator;
import java.util.SortedMap;

@Slf4j
public abstract class Transfer {

    public SendResult send(String merchantId, String secret, String appId, String openId, String orderId, String desc, int amount) {
        boolean tansferStatus = false;

        String responseInfo = "";
        String xml = wxSendWallet(merchantId, secret, appId, openId, orderId, desc, amount);
        try {//指定读取证书格式为PKCS12

            KeyStore keyStore = KeyStore.getInstance("PKCS12");

            String certName = getCert();

            InputStream instream = Thread.currentThread().getContextClassLoader().getResourceAsStream(certName);

            try {

                keyStore.load(instream, merchantId.toCharArray());

            } finally {

                instream.close();

            }

            SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, merchantId.toCharArray()).build();

            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslcontext,
                    new String[] { "TLSv1.2" },
                    null,
                    SSLConnectionSocketFactory.getDefaultHostnameVerifier());

            CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

            HttpPost httppost = new HttpPost(getUrl());

            httppost.addHeader("Content-Type", "text/xml");

            StringEntity se = new StringEntity(xml, "UTF-8");

            httppost.setEntity(se);

            CloseableHttpResponse responseEntry = httpclient.execute(httppost);
            try {

                HttpEntity entity = responseEntry.getEntity();
                if (entity != null) {
                    SAXReader saxReader = new SAXReader();

                    Document document = saxReader.read(entity.getContent());
                    log.info("receive pay result:{}", document.asXML());

                    Element rootElt = document.getRootElement();

                    String resultCode = rootElt.elementText("result_code");
                    if (resultCode.equals("SUCCESS")) {
                        tansferStatus = true;
                        //成功后操作
                    } else {
                        //失败后操作
                        responseInfo = rootElt.elementText("err_code_des");
                    }

                }

                EntityUtils.consume(entity);

            } catch (Exception e) {
                log.error(e.getMessage(), e);
            } finally {

                responseEntry.close();

            }

        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        return new SendResult(tansferStatus, responseInfo, amount);

    }

    abstract protected String wxSendWallet(String merchantId, String secret, String appId, String openId, String orderId, String actName, int amount);

    abstract protected String getUrl();

    abstract protected String getCert();

    protected String generateSignature(SortedMap parameters, String secret) {
        StringBuilder sb = new StringBuilder();

        Iterator iterator = parameters.keySet().iterator();

        while (iterator.hasNext()) {
            String key = (String) iterator.next();

            String value = String.valueOf(parameters.get(key));

            sb.append(key);
            sb.append("=");
            sb.append(value);
            sb.append("&");
        }

        sb.append("key");
        sb.append("=");
        sb.append(secret);

        log.info("sing string:{}", sb.toString());

        return DigestUtils.md5Hex(sb.toString()).toUpperCase();
    }

    protected String mapToXml(SortedMap parameters) {
        StringBuilder sb = new StringBuilder();

        sb.append("<xml>");
        Iterator iterator = parameters.keySet().iterator();

        while (iterator.hasNext()) {
            String key = (String) iterator.next();

            String value = String.valueOf(parameters.get(key));

            sb.append("<");
            sb.append(key);
            sb.append(">");
            sb.append(value);
            sb.append("</");
            sb.append(key);
            sb.append(">");
        }

        sb.append("</xml>");

        return sb.toString();
    }

}
